package com.ms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ms.constant.MessageConstant;
import com.ms.context.BaseContext;
import com.ms.domain.dto.AlbumCreateDTO;
import com.ms.domain.dto.AlbumUpdateDTO;
import com.ms.domain.entity.Album;
import com.ms.domain.entity.Genre;
import com.ms.domain.entity.Music;
import com.ms.domain.entity.User;
import com.ms.exception.BusinessException;
import com.ms.exception.PermissionDeniedException;
import com.ms.exception.ResourceNotFoundException;
import com.ms.mapper.AlbumMapper;
import com.ms.mapper.GenreMapper;
import com.ms.mapper.MusicMapper;
import com.ms.mapper.UserMapper;
import com.ms.service.AlbumService;
import com.ms.utiles.OssUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.Arrays;
import java.util.List;


@Service
@Slf4j
@RequiredArgsConstructor
public class AlbumServiceImpl implements AlbumService {
    private final AlbumMapper albumMapper;
    private final MusicMapper musicMapper;
    private final OssUtil ossUtil;
    private final UserMapper userMapper;
    private final GenreMapper genreMapper;

    /**
     * 创建专辑
     *
     * @param dto        创建专辑的数据
     * @param coverImage 专辑封面图片
     * @return 创建的专辑
     */
    @Override
    @Transactional
    public Album createAlbum(AlbumCreateDTO dto, MultipartFile coverImage) {
        // 设置当前用户为创建者
        dto.setCreatorId(BaseContext.getCurrentId());
        log.info("用户{}创建专辑：{}", dto.getCreatorId(), dto);

        String coverUrl = null;
        if (coverImage != null) {
            log.info("开始上传封面图片...");
            coverUrl = ossUtil.uploadFile(coverImage, "image");
            log.info("封面图片上传成功: {}", coverUrl);
        }

        Album album = Album.builder()
                .title(dto.getTitle())
                .description(dto.getDescription())
                .coverUrl(coverUrl)
                .creatorId(dto.getCreatorId())
                .build();

        albumMapper.insert(album);
        return album;
    }

    /**
     * 修改专辑
     *
     * @param dto
     */
    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = "album", key = "T(com.ms.constant.CacheConstant).ALBUM_BY_ID + ':' + #dto.id"),
            @CacheEvict(value = "album", key = "T(com.ms.constant.CacheConstant).ALBUM_PAGE + '*'"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_LIST_BY_ALBUM + ':' + #dto.id"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE_BY_ALBUM + ':' + #dto.id + '*'")
    })
    public void updateAlbum(AlbumUpdateDTO dto) {
        Album album = albumMapper.selectById(dto.getId());
        if (album == null) {
            throw new ResourceNotFoundException(MessageConstant.ALBUM_NOT_FOUND);
        }

        // 权限检查：只能修改自己的专辑
        if (!album.getCreatorId().equals(BaseContext.getCurrentId())) {
            throw new PermissionDeniedException(MessageConstant.PERMISSION_DENIED);
        }

        Album updateEntity = new Album();
        updateEntity.setId(dto.getId());
        updateEntity.setTitle(dto.getTitle());
        updateEntity.setDescription(dto.getDescription());

        // 更新封面
        if (dto.getCoverUrl() != null && !dto.getCoverUrl().equals(album.getCoverUrl())) {
            // 删除旧封面
            ossUtil.deleteFile(album.getCoverUrl());
            updateEntity.setCoverUrl(dto.getCoverUrl());
        }

        albumMapper.updateById(updateEntity);
    }

    /**
     * 根据id删除专辑
     *
     * @param id
     */
    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = "album", key = "T(com.ms.constant.CacheConstant).ALBUM_BY_ID + ':' + #id"),
            @CacheEvict(value = "album", key = "T(com.ms.constant.CacheConstant).ALBUM_PAGE + '*'"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_LIST_BY_ALBUM + ':' + #id"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE_BY_ALBUM + ':' + #id + '*'")
    })
    public void deleteAlbum(Integer id) {
        Album album = albumMapper.selectById(id);
        if (album == null) return;

        // 权限检查：只能删除自己的专辑
        if (!album.getCreatorId().equals(BaseContext.getCurrentId())) {
            throw new PermissionDeniedException(MessageConstant.PERMISSION_DENIED);
        }

        // 删除专辑封面
        ossUtil.deleteFile(album.getCoverUrl());

        // 解除音乐与专辑的关联
        musicMapper.update(null,
                Wrappers.<Music>lambdaUpdate()
                        .set(Music::getAlbumId, null)
                        .eq(Music::getAlbumId, id));

        // 删除专辑
        albumMapper.deleteById(id);
    }

    /**
     * 根据id获取专辑
     *
     * @param id 专辑ID
     * @return 专辑信息
     */
    @Override
    @Cacheable(value = "album", key = "T(com.ms.constant.CacheConstant).ALBUM_BY_ID + ':' + #id",
            unless = "#result == null")
    public Album getAlbumById(Integer id) {
        Album album = albumMapper.selectById(id);
        if (album == null) {
            throw new ResourceNotFoundException(MessageConstant.ALBUM_NOT_FOUND);
        }

        // 填充专辑中的音乐
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.eq("album_id", id)
                .eq("status", "APPROVED")
                .orderByAsc("create_time");

        List<Music> musicList = musicMapper.selectList(query);
        musicList.forEach(this::fillMusicDetails);
        album.setMusicList(musicList);
        album.setCreatorName(userMapper.selectById(album.getCreatorId()).getNickname());

        return album;
    }

    /**
     * 添加音乐到专辑
     *
     * @param albumId
     * @param musicId
     */
    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = "album", key = "T(com.ms.constant.CacheConstant).ALBUM_BY_ID + ':' + #albumId"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_LIST_BY_ALBUM + ':' + #albumId"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE_BY_ALBUM + ':' + #albumId + '*'")
    })
    public void addMusicToAlbum(Integer albumId, Integer musicId) {
        Album album = albumMapper.selectById(albumId);
        if (album == null) {
            throw new ResourceNotFoundException(MessageConstant.ALBUM_NOT_FOUND);
        }

        Music music = musicMapper.selectById(musicId);
        if (music == null) {
            throw new ResourceNotFoundException(MessageConstant.MUSIC_NOT_FOUND);
        }

        // 权限检查：只能管理自己的专辑和音乐
        String[] userIds = music.getCreatorIds().split("-");
        if (userIds.length == 0) {
            throw new BusinessException(MessageConstant.USER_NOT_FOUND);
        }

        // 更新专辑封面（如果专辑没有封面）
        if (StringUtils.isBlank(album.getCoverUrl()) &&
                StringUtils.isNotBlank(music.getCoverUrl())) {
            album.setCoverUrl(music.getCoverUrl());
            albumMapper.updateById(album);
        }

        // 更新音乐的专辑ID
        music.setAlbumId(albumId);
        musicMapper.updateById(music);
    }

    /**
     * 移除音乐
     *
     * @param albumId
     * @param musicId
     */
    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = "album", key = "T(com.ms.constant.CacheConstant).ALBUM_BY_ID + ':' + #albumId"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_LIST_BY_ALBUM + ':' + #albumId"),
            @CacheEvict(value = "music", key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE_BY_ALBUM + ':' + #albumId + '*'")
    })
    public void removeMusicFromAlbum(Integer albumId, Integer musicId) {
        Music music = musicMapper.selectById(musicId);
        if (music == null || !music.getAlbumId().equals(albumId)) {
            return; // 音乐不存在或不属于该专辑
        }

        // 权限检查：只能管理自己的专辑和音乐
        Album album = albumMapper.selectById(albumId);
        if (!album.getCreatorId().equals(BaseContext.getCurrentId()) ||
                music.getCreatorIds().split(",").length == 0) {
            throw new PermissionDeniedException(MessageConstant.PERMISSION_DENIED);
        }

        // 解除关联
        music.setAlbumId(null);
        musicMapper.updateById(music);
    }

    /**
     * 获取用户专辑
     *
     * @param userId
     * @return
     */
    @Override
    @Cacheable(value = "album",
            key = "T(com.ms.constant.CacheConstant).ALBUM_LIST_BY_USER + ':' + #userId",
            unless = "#result == null || #result.isEmpty()")
    public List<Album> getUserAlbums(Integer userId) {
        // 权限检查：只能查看自己的专辑
        if (!userId.equals(BaseContext.getCurrentId())) {
            throw new PermissionDeniedException(MessageConstant.PERMISSION_DENIED);
        }

        QueryWrapper<Album> query = new QueryWrapper<>();
        query.eq("creator_id", userId)
                .orderByDesc("create_time");

        return albumMapper.selectList(query);
    }

    /**
     * 获取用户专辑分页
     *
     * @param userId
     * @param page
     * @param size
     * @return
     */
    @Override
    @Cacheable(value = "album",
            key = "T(com.ms.constant.CacheConstant).ALBUM_PAGE_BY_USER + ':' + #userId + ':' + #page + ':' + #size",
            unless = "#result == null || #result.records.isEmpty()")
    public Page<Album> getUserAlbumsPage(Integer userId, Integer page, Integer size) {
        // 权限检查：只能查看自己的专辑
        if (!userId.equals(BaseContext.getCurrentId())) {
            throw new PermissionDeniedException(MessageConstant.PERMISSION_DENIED);
        }

        Page<Album> pageInfo = new Page<>(page, size);
        QueryWrapper<Album> query = new QueryWrapper<>();
        query.eq("creator_id", userId)
                .orderByDesc("create_time");

        albumMapper.selectPage(pageInfo, query);
        pageInfo.getRecords().forEach(this::fillAlbumDetails);
        return pageInfo;
    }

    /**
     * 获取专辑分页
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    @Cacheable(value = "album",
            key = "T(com.ms.constant.CacheConstant).ALBUM_PAGE + ':' + #page + ':' + #size",
            unless = "#result == null || #result.records.isEmpty()")
    public Page<Album> getAlbumPage(Integer page, Integer size) {
        Page<Album> pageInfo = new Page<>(page, size);
        QueryWrapper<Album> query = new QueryWrapper<>();
        query.orderByDesc("create_time");

        albumMapper.selectPage(pageInfo, query);

        pageInfo.getRecords().forEach(this::fillAlbumDetails);
        return pageInfo;
    }

    /**
     * 获取专辑中的音乐
     *
     * @param albumId
     * @return
     */
    @Override
    @Cacheable(value = "music",  // 注意：这里使用music缓存区域
            key = "T(com.ms.constant.CacheConstant).MUSIC_LIST_BY_ALBUM + ':' + #albumId",
            unless = "#result == null || #result.isEmpty()")
    public List<Music> getMusicByAlbumId(Integer albumId) {
        log.info("获取专辑 {} 中的音乐", albumId);
        Album album = albumMapper.selectById(albumId);
        if (album == null) {
            throw new ResourceNotFoundException(MessageConstant.ALBUM_NOT_FOUND);
        }
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.eq("album_id", albumId)
                .eq("status", "APPROVED")
                .orderByAsc("create_time");

        List<Music> musicList = musicMapper.selectList(query);
        musicList.forEach(this::fillMusicDetails);
        return musicList;
    }

    /**
     * 获取专辑中的音乐分页
     *
     * @param albumId
     * @param page
     * @param size
     * @return
     */
    @Override
    @Cacheable(value = "music",  // 注意：这里使用music缓存区域
            key = "T(com.ms.constant.CacheConstant).MUSIC_PAGE_BY_ALBUM + ':' + #albumId + ':' + #page + ':' + #size",
            unless = "#result == null || #result.records.isEmpty()")
    public Page<Music> getMusicPageByAlbumId(Integer albumId, Integer page, Integer size) {
        log.info("分页获取专辑 {} 中的音乐，页码：{}，大小：{}", albumId, page, size);
        Album album = albumMapper.selectById(albumId);
        if (album == null) {
            throw new ResourceNotFoundException(MessageConstant.ALBUM_NOT_FOUND);
        }

        Page<Music> pageInfo = new Page<>(page, size);
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.eq("album_id", albumId)
                .eq("status", "APPROVED")
                .orderByAsc("create_time");

        musicMapper.selectPage(pageInfo, query);
        pageInfo.getRecords().forEach(this::fillMusicDetails);
        return pageInfo;
    }

    /**
     * 填充专辑的详细信息
     *
     * @param album
     */
    private void fillAlbumDetails(Album album) {
        // 填充创建者id
        User creator = userMapper.selectById(album.getCreatorId());
        if (creator != null) {
            album.setCreatorName(creator.getUsername());
        }
        // 填充专辑中的音乐
        QueryWrapper<Music> query = new QueryWrapper<>();
        query.eq("album_id", album.getId())
                .eq("status", "APPROVED")
                .orderByAsc("create_time");
        List<Music> musicList = musicMapper.selectList(query);
        album.setMusicList(musicList);
    }

    /**
     * 填充音乐的详细信息
     */
    private void fillMusicDetails(Music music) {
        // 填充创建者名称
        String[] userIds = music.getCreatorIds().split("-");
        List<User> creators = userMapper.selectByIds(Arrays.asList(userIds));
        if (creators != null) {
            List<String> creatorNames = creators.stream()
                    .map(User::getUsername)
                    .toList();
            music.setCreatorName(creatorNames);
        }
        log.info("填充音乐 {} 的创建者名称 {}", music.getId(), music.getCreatorName());

        // 填充曲风名称
        Genre genre = genreMapper.selectById(music.getGenreId());
        if (genre != null) {
            music.setGenreName(genre.getName());
        }

        // 填充专辑名称
        if (music.getAlbumId() != null) {
            Album album = albumMapper.selectById(music.getAlbumId());
            if (album != null) {
                music.setAlbumTitle(album.getTitle());
            }
        }
    }
}